/*
 *  Copyright 2005 The Apache Software Foundation
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */
package org.mybatis.generator.api;

import java.io.File;

import org.mybatis.generator.exception.ShellException;

/**
 * This interface defines methods that a shell should support to enable the generator to work. A "shell" is defined as the execution environment (i.e. an Eclipse plugin, and Ant task, a NetBeans
 * plugin, etc.)
 * 
 * The default ShellCallback that is very low function and does not support the merging of Java files. The default shell callback is appropriate for use in well controlled environments where no
 * changes made to generated Java files.
 * 
 * @author Jeff Butler
 */
public interface ShellCallback
{
    /**
     * This method is called to ask the shell to resolve a project/package combination into a directory on the file system. This method is called repeatedly (once for each generated file), so it would
     * be wise for an implementing class to cache results.
     * 
     * The returned <code>java.io.File</code> object:
     * <ul>
     * <li>Must be a directory</li>
     * <li>Must exist</li>
     * </ul>
     * 
     * The default shell callback interprets both values as directories and simply concatenates the two values to generate the default directory.
     * 
     * @param targetProject
     * @param targetPackage
     * @return the directory (must exist)
     * @throws ShellException if the project/package cannot be resolved into a directory on the file system. In this case, the generator will not save the file it is currently working on. The
     *             generator will add the exception message to the list of warnings automatically.
     */
    File getDirectory(String targetProject, String targetPackage)
        throws ShellException;
    
    /**
     * This method is called if a newly generated Java file would overwrite an existing file. This method should return the merged source (formatted). The generator will write the merged source as-is
     * to the file system.
     * 
     * A merge typically follows these steps:
     * <ol>
     * <li>Delete any methods/fields in the existing file that have the specified JavaDoc tag</li>
     * <li>Add any new super interfaces from the new file into the existing file</li>
     * <li>Make sure that the existing file's super class matches the new file</li>
     * <li>Make sure that the existing file is of the same type as the existing file (either interface or class)</li>
     * <li>Add any new imports from the new file into the existing file</li>
     * <li>Add all methods and fields from the new file into the existing file</li>
     * <li>Format the resulting source string</li>
     * </ol>
     * 
     * This method is called only if you return <code>true</code> from <code>isMergeSupported()</code>.
     * 
     * @param newFileSource the source of the newly generated Java file
     * @param existingFileFullPath the fully qualified path name of the existing Java file
     * @param javadocTags the JavaDoc tags that denotes which methods and fields in the old file to delete (if the Java element has any of these tags, the element is eligible for merge)
     * @param fileEncoding the file encoding for reading existing Java files. Can be null, in which case the platform default encoding will be used.
     * @return the merged source, properly formatted. The source will be saved exactly as returned from this method.
     * @throws ShellException if the file cannot be merged for some reason. If this exception is thrown, nothing will be saved and the existing file will remain undisturbed. The generator will add the
     *             exception message to the list of warnings automatically.
     */
    String mergeJavaFile(String newFileSource, String existingFileFullPath, String[] javadocTags, String fileEncoding)
        throws ShellException;
    
    /**
     * After all files are saved to the file system, this method is called once for each unique project that was affected by the generation run. This method is useful if your IDE needs to be informed
     * that file system objects have been created or updated. If you are running outside of an IDE, your implementation need not do anything in this method.
     * 
     * @param project the project to be refreshed
     */
    void refreshProject(String project);
    
    /**
     * Return true if the callback supports Java merging, otherwise false. The <code>mergeJavaFile()</code> method will be called only if this method returns <code>true</code>.
     * 
     * @return a boolean specifying whether Java merge is supported or not
     */
    boolean isMergeSupported();
    
    /**
     * Return true if the generator should overwrite an existing file if one exists. This method will be called only if <code>isMergeSupported()</code> returns <code>false</code> and a file exists
     * that would be overwritten by a generated file. If you return <code>true</code>, then we will log a warning specifying what file was overwritten.
     * 
     * @return true if you want to overwrite existing files
     */
    boolean isOverwriteEnabled();
}
